/*
 * libnss_ato.c
 *
 * nss module to map every requested user to a fixed one.
 * ato is All To One as all users get mapped to one
 * predefined user
 *
 * Copyright (c) Pietro Donatini, 2007.
 *
 * this product may be distributed under the terms of
 * the GNU Lesser Public License.
 *
 * version 0.2
 *
 * CHANGELOG:
 * strip end of line in reading /etc/libnss-ato
 * suggested by Kyler Laird
 *
 * TODO:
 *
 * check bugs
 *
 */

#include <nss.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<iostream>
#include<signal.h>
/* #include <syslog.h> */

/* for security reasons */
#define MIN_UID_NUMBER   500
#define MIN_GID_NUMBER   500
#define MACH_NAME "/etc/hostname"
using namespace std;
/*
 * The passwd structure in <pwd.h>
struct passwd
{
	char *pw_name;                Username.
	char *pw_passwd;              Password.
	__uid_t pw_uid;               User ID.
	__gid_t pw_gid;               Group ID.
	char *pw_gecos;               Real name.
	char *pw_dir;                 Home directory.
	char *pw_shell;               Shell program.
};

shadow passwd structure in <shadow.h>

struct spwd
{
	char *sp_namp;          Login name
	char *sp_pwdp;          Encrypted password
	long sp_lstchg;         Date of last change
	long sp_min;            Min #days between changes
	long sp_max;            Max #days between changes
	long sp_warn;           #days before pwd expires to warn user to change it
	long sp_inact;          #days after pwd expires until account is disabled
	long sp_expire;         #days since 1970-01-01 until account is disabled
	unsigned long sp_flag;  Reserved
};

*/

/*  What can be configured in /etc/libnss-ato.conf */
typedef struct ato_conf {
	char *pw_name;
	char *pw_gecos;
	char *pw_dir;
	char *pw_shell;
	__uid_t pw_uid;
	__gid_t pw_gid;
} ato_conf_t;
struct Machnamestruct
{
    int  Enable;
    char Machname[100];
};
//返回本机名
struct Machnamestruct
readMachname()
{
    struct Machnamestruct Mach;
    memset(&Mach,0x00,sizeof(struct Machnamestruct));
    FILE *fd;
	char buff[100];
	if ((fd = fopen(MACH_NAME, "r")) == NULL )
	{
        Mach.Enable=0;
	}
	//读取机器名字到buff
    if (fgets (buff, BUFSIZ, fd) == NULL)
    {
		fclose(fd);
        Mach.Enable=0;
	}
	Mach.Enable=1;
	strcpy(Mach.Machname,buff);
	return Mach;

}
//请求数据格式
/*
*struct
*RequInfo:
*Param:
*Machname:
*/
struct passwdbuff
{
        char pw_name[100];              //  Username.
		char pw_passwd[100];             // Password.
		__uid_t pw_uid;              // User ID.
		__gid_t pw_gid;             //  Group ID.
		char pw_gecos[100];              // Real name.
		char pw_dir[100];                // Home directory.
		char pw_shell[100];             //  Shell program.

};
 struct RequInfo
      {
        char RequInfo[100];
        char Param[100];
        char Machname[100];
      };

/*
 * the configuration /etc/libnss-ato.conf is just one line
 * whith the local user data as in /etc/passwd. For example:
 * dona:x:1001:1001:P D ,,,:/home/dona:/bin/bash
 * test_user:x:1000:1000:Test User,,,:/home/test:/bin/bash
 * conf->pw_name
 * conf->pw_uid
 * conf->pw_gid
 * conf->pw_gecos
 * conf->pw_dir
 * conf->pw_shell
 *
 */


/*
 * Allocate some space from the nss static buffer.  The buffer and buflen
 *    are the pointers passed in by the C library to the _nss_ntdom_*
 *       functions.
 *
 *  Taken fron glibc
 *
 */





int main()
{
        signal(SIGPIPE,SIG_IGN);
        char name[100]="thua";
        struct passwd *p;
        struct RequInfo Req;
        memset(&Req,0x00,sizeof(struct RequInfo));
        strcpy(Req.RequInfo,"USER");
        strcpy(Req.Param,name);
        struct Machnamestruct Resu=readMachname();
        if(Resu.Enable)
            strcpy(Req.Machname,Resu.Machname);
        else
        {
            return 0;
        }

        //socket 通信
        struct sockaddr_in stSockAddr;
        int Res;
        //套接字描述
        int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (-1 == SocketFD) return 0;
        //清空
        memset(&stSockAddr, 0, sizeof(struct sockaddr_in));

        stSockAddr.sin_family = AF_INET;
        stSockAddr.sin_port = htons(5555);//服务器端口号
        Res = inet_pton(AF_INET, "211.87.230.12", &stSockAddr.sin_addr);//服务器IP地址（转换为网络字节）

        if (0 >= Res)return 0;
        if (-1 == connect(SocketFD, (const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in))) return 0;
        //发送参数到服务器
        send(SocketFD,&Req,sizeof(Req),0);

        char buffer1[1000];
        memset(buffer1,0x00,sizeof(buffer1));

        if(read(SocketFD,buffer1,sizeof(buffer1))<0)
        {
            cout<<"读取数据错误！"<<endl;
            close(SocketFD);
        }
        struct passwdbuff pbuff;

        memcpy(&pbuff,buffer1,sizeof(pbuff));

        //cout<<"pd UID"<<temp<<endl;
        p=(passwd * )malloc(sizeof(pbuff));
        p->pw_name=(char *)malloc(100);
        p->pw_passwd=(char *)malloc(100);
        p->pw_dir=(char *)malloc(100);
        p->pw_shell=(char *)malloc(100);
        //p->pw_uid=(__uid_t)malloc(100);
        //p->pw_gid=(__gid_t)malloc(100);
        //bcopy(p,&pbuff,sizeof(p));
        strcpy(p->pw_name,pbuff.pw_name);
        strcpy(p->pw_passwd,pbuff.pw_passwd);
        strcpy(p->pw_dir,pbuff.pw_dir);
        strcpy(p->pw_shell,pbuff.pw_shell);
        p->pw_uid=pbuff.pw_uid;
        p->pw_gid=pbuff.pw_gid;

        cout<<"p的大小是"<<sizeof(p)<<endl;
        cout<<"buffer1的大小是"<<sizeof(buffer1)<<endl;
        cout<<p->pw_name<<endl;
        cout<<p->pw_uid<<endl;
       cout<<"send 数据大小是："<<send(SocketFD,&p,sizeof(p),0)<<endl;

        close(SocketFD);
        return 0;

}
